<script setup lang="ts">
import axios from '../axios';
import { ElMessage, ElMessageBox, MessageBoxData, UploadFile, UploadFiles, UploadUserFile } from 'element-plus';
import { reactive, ref } from 'vue';
import { Question, QuestionType, questionTypeToString, QuestionChoice, Application, ResourceResponse, ApplicationInfo, Status } from '../model'
import { router } from '../router';

const props = defineProps<{
    mode: 'edit' | 'fill' | 'show',
    templateId?: number,
    applicationId?: number,
}>()
type QuestionAndAnswer = Question & {answer: string | number[] | string[]}
const questions = ref<QuestionAndAnswer[]>([])
const application = ref<ApplicationInfo>()
const choices = reactive<Map<number, {i: number, name: string}[]>>(new Map())

const getChoices = async (questionId: number): Promise<{i: number, name: string}[]> => {
    const res = await axios.get(`/template/question/choice?questionId=${questionId}`)
    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '查询问题选项失败',
        })
        return []
    }
    const choices: QuestionChoice[] = await res.data['choices']
    return choices.map(q => {
        return {i: q.choiceNumber, name: q.name}
    })
}

const addChoice = (questionId: number) => {
    const l = choices.get(questionId)!
    l.push({
        i: l.length + 1,
        name: '新选项',
    })
    modifyChoice(questionId)
}

const deleteChoice = async (questionId: number, choiceNum: number) => {
    choices.get(questionId)!.splice(choiceNum-1, 1)
    modifyChoice(questionId)
}

const modifyChoice = async (questionId: number) => {
    const names = choices.get(questionId)!.map(choice => choice.name)
    const res = await axios.post(`/admin/template/question/choice`, {
        questionId: questionId,
        names: names,
    })
    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '设置问题选项失败',
        })
        return
    }
    loadData()
}

const addQuestion = async () => {
    const res = await axios.post(`/admin/template/question`, {
        templateId: props.templateId,
        title: '未命名问题',
        type: QuestionType.TEXT,
    })

    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '创建问题失败',
        })
        return
    }
    loadData()
}

const modifyQuestion = async (question: Question) => {
    const res = await axios.put(`/admin/template/question`, {
        questionId: question.id,
        ...question
    })
    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '修改问题失败',
        })
        return
    }
    loadData()
}

const deleteQuestion = async (questionId: number) => {
    try {
        await ElMessageBox.confirm('你确定要删除吗', {
            cancelButtonText: '取消',
            confirmButtonText: '确定',
            type: 'warning',
        })
    } catch {
        return
    }

    const res = await axios.delete(`/admin/template/question`, {
        data: {
            questionId: questionId,
        }
    })
    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '删除问题失败',
        })
        return
    }
    loadData()
}

const swapQuestion = async (questionId1: number, questionId2: number) => {
    const res = await axios.post(`/admin/template/question/swap`, {
        questionId1: questionId1,
        questionId2: questionId2,
    })
    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '交换问题失败',
        })
        return
    }
    loadData()
}

const loadData = async () => {
    let templateId = props.templateId
    if (props.applicationId !== undefined) {
        const res = await axios.get(`/applicationInfo?applicationId=${props.applicationId}`)
        if (!res.data['ok']) {
            ElMessage({
                type: 'error',
                message: '查询申请信息失败',
            })
            return
        }
        application.value = res.data
        templateId = application.value!.template.id
    }
    const res = await axios.get(`/template/question?templateId=${templateId}`)
    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '查询审批流问题失败',
        })
        return
    }
    questions.value = res.data['questions']
    choices.clear()
    for (const question of questions.value) {
        if (question.type == QuestionType.SINGLE_CHOICE || question.type == QuestionType.MULTI_CHOICE) {
            choices.set(question.id, await getChoices(question.id))
        }
    }


}
loadData()


// 填写模式
const submitApplication = async () => {
    const res = await axios.post(`/applicant/application`, {
        templateId: props.templateId,
        answers: questions.value.map(q => {
            console.log(q)
            let ans: string
            if (q.type == QuestionType.IMAGE || q.type == QuestionType.MULTI_CHOICE) {
                ans = q.answer !== undefined ? (<any[]> q.answer).join(',') : ''
            } else {
                ans = <string> q.answer
            }
            
            return {
                questionId: q.id,
                answer: ans,
            }
        })
    })
    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '提交申请失败',
        })
        return
    }

    ElMessage({
        type: 'success',
        message: '提交成功',
    })
    router.push('/application')
}

const onImageUploaded = async (response: ResourceResponse, uploadFile: UploadFile, uploadFiles: UploadFiles, qaa: QuestionAndAnswer) => {
    if (!response.ok) {
        ElMessage({
            type: 'error',
            message: '查询审批流问题失败',
        })
        return
    }

    if (qaa.answer === undefined) {
        qaa.answer = []
    }

    (<string[]> qaa.answer).push(response.sha)
}
const dialogVisible = ref(false)
const dialogImageUrl = ref('')
const previewImage = (uploadFile: UploadFile) => {
    dialogImageUrl.value = uploadFile.url!
    dialogVisible.value = true
}


const approve = async (approve: boolean) => {
    let opinion: MessageBoxData
    try {
        opinion = await ElMessageBox.prompt(
            '',
            `正在${approve ? '同意' : '拒绝'}审批: ${application.value?.template.tableName}`, {
                inputPlaceholder: `请填写审批意见`,
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                inputType: 'textarea',
            }
        )
    } catch (e) {
        return
    }
    if (!approve && opinion.value == null) {
        ElMessage({
            type: 'error',
            message: '请填写拒绝原因',
        })
        return
    }
    
    const res = await axios.post('/approver/application', {
        applicationId: props.applicationId,
        approve: approve,
        opinion: opinion.value,
    })

    if (!res.data['ok']) {
        ElMessage({
            type: 'error',
            message: '审批失败',
        })
        return
    }
    ElMessage({
        type: 'success',
        message: `${approve ? '同意' : '拒绝'}审批成功`,
    })
    router.back()
}

</script>

<template>
    <div class="questions">
        <el-dialog v-model="dialogVisible">
            <el-image :src="dialogImageUrl" fit="contain" />
        </el-dialog>
        <div class="question-row" v-for="question in questions" :key="question.id">
            <div class="question-main">
                <div class="question-number">{{ question.questionNumber }}.</div>
                <div class="question-content">
                    <!-- 问题标题 -->
                    <el-input style="margin-bottom: 10px;" v-if="props.mode == 'edit'" class="question-title" v-model="question.title" @blur="() => modifyQuestion(question)" />
                    <div style="margin-bottom: 10px; font-weight: bold; font-size: large; color: #303133;" v-if="props.mode != 'edit'" class="question-title">{{ question.title }}</div>

                    <!-- 填空题 -->
                    <el-input style="margin-bottom: 10px" :disabled="props.mode != 'fill'" placeholder="填写回答" v-model="question.answer" v-if="question.type == QuestionType.TEXT && props.mode != 'show'" clearable />
                    <el-input style="margin-bottom: 10px" readonly placeholder="未填写回答" :value="application?.questions[question.questionNumber-1].answer?.answer" v-if="question.type == QuestionType.TEXT && props.mode == 'show'" />
                    <!-- 日期题 -->
                    <el-date-picker style="margin-bottom: 10px; width: 100%" :disabled="props.mode != 'fill'" v-if="question.type == QuestionType.DATE && props.mode != 'show'" placeholder="选择日期" v-model="question.answer" value-format="YYYY-MM-DD" clearable />
                    <el-date-picker style="margin-bottom: 10px; width: 100%" readonly :model-value="application?.questions[question.questionNumber-1].answer?.answer" v-if="question.type == QuestionType.DATE && props.mode == 'show'" placeholder="未选择日期" value-format="YYYY-MM-DD" />
                    <!-- 时间题 -->
                    <el-time-picker style="margin-bottom: 10px; width: 100%" :disabled="props.mode != 'fill'" v-if="question.type == QuestionType.TIME && props.mode != 'show'" placeholder="选择时间" v-model="question.answer" value-format="HH:mm:ss" clearable />
                    <el-time-picker style="margin-bottom: 10px; width: 100%" readonly v-if="question.type == QuestionType.TIME && props.mode == 'show'" placeholder="未选择时间" :model-value="application?.questions[question.questionNumber-1].answer?.answer" value-format="HH:mm:ss" />
                    <!-- 单选题 -->
                    <el-radio-group v-if="question.type == QuestionType.SINGLE_CHOICE && props.mode != 'show'" v-model="question.answer">
                        <el-radio style="margin-bottom: 10px" :disabled="props.mode != 'fill'" v-for="choice in choices.get(question.id)" :key="choice.i" :label="choice.i">
                            <div v-if="props.mode != 'edit'">{{ choice.name }}</div>
                            <div v-else>
                                <el-input v-model="choice.name" @blur="() => modifyChoice(question.id)">
                                    <template #suffix>
                                        <el-icon class="icon-button" @click="deleteChoice(question.id, choice.i)">
                                            <Close />
                                        </el-icon>
                                    </template>
                                </el-input>
                            </div>
                        </el-radio>
                        <el-button v-if="props.mode == 'edit'" style="margin-bottom: 10px; width: 50px" @click="() => addChoice(question.id)">+</el-button>
                    </el-radio-group>
                    <el-radio-group v-if="question.type == QuestionType.SINGLE_CHOICE && props.mode == 'show'" :model-value="parseInt(application?.questions[question.questionNumber-1].answer?.answer!)">
                        <el-radio style="margin-bottom: 10px" v-for="choice in choices.get(question.id)" :key="choice.i" :label="choice.i">
                            <div>{{ choice.name }}</div>
                        </el-radio>
                    </el-radio-group>
                    <!-- 多选题 -->
                    <el-checkbox-group v-if="question.type == QuestionType.MULTI_CHOICE && props.mode != 'show'" v-model="question.answer">
                        <el-checkbox style="margin-bottom: 10px; margin-right: 30px;" :disabled="props.mode != 'fill'" v-for="choice in choices.get(question.id)" :label="choice.i" :key="choice.i">
                            <div v-if="props.mode != 'edit'">{{ choice.name }}</div>
                            <div v-else>
                                <el-input v-model="choice.name" @blur="modifyChoice(question.id)">
                                    <template #suffix>
                                        <el-icon class="icon-button" @click="deleteChoice(question.id, choice.i)">
                                            <Close />
                                        </el-icon>
                                    </template>
                                
                                </el-input>
                            </div>
                        </el-checkbox>
                        <el-button v-if="props.mode == 'edit'" style="margin-bottom: 10px; width: 50px" @click="() => addChoice(question.id)">+</el-button>
                    </el-checkbox-group>
                    <el-checkbox-group v-if="question.type == QuestionType.MULTI_CHOICE && props.mode == 'show'" :model-value="application?.questions[question.questionNumber-1].answer?.answer!.split(',').map(t => parseInt(t))">
                        <el-checkbox style="margin-bottom: 10px; margin-right: 30px;" v-for="choice in choices.get(question.id)" :label="choice.i" :key="choice.i">
                            <div>{{ choice.name }}</div>
                        </el-checkbox>
                    </el-checkbox-group>
                    <!-- 图片题 -->
                    <el-upload
                        v-if="question.type == QuestionType.IMAGE && props.mode != 'show'"
                        list-type="picture-card"
                        :disabled="props.mode != 'fill'"
                        multiple
                        v-model="question.answer"
                        action="/api/resource"
                        :on-success="(r: ResourceResponse, f: UploadFile, fs: UploadFiles) => onImageUploaded(r, f, fs, question)"
                        :on-preview="previewImage"
                    >
                        <el-icon><Plus /></el-icon>
                    </el-upload>
                    <el-upload
                        v-if="question.type == QuestionType.IMAGE && props.mode == 'show'"
                        list-type="picture-card"
                        disabled
                        multiple
                        :file-list="application?.questions[question.questionNumber-1].answer?.answer!.split(',').map(sha => {return {url: `/api/resource/${sha}`}})"
                        :on-preview="previewImage"
                    >
                        <el-icon><Plus /></el-icon>
                    </el-upload>
                </div>
                <div class="question-type" v-if="props.mode == 'edit'">
                    <el-select placeholder="选择类型" v-model="question.type" @change="() => modifyQuestion(question)">
                        <el-option
                            v-for="t in QuestionType"
                            :key="t"
                            :label="questionTypeToString(t)"
                            :value="t"
                        />
                    </el-select>
                </div>
                <div class="question-control" v-if="props.mode == 'edit'">
                    <div class="question-close" @click="() => deleteQuestion(question.id)">
                        <el-icon class="icon-button">
                            <close />
                        </el-icon>
                    </div>
                    <div class="question-move">
                        <el-icon class="icon-button" v-if="question.questionNumber != 1" @click="() => swapQuestion(question.id, questions[question.questionNumber - 2].id)">
                            <ArrowUp />
                        </el-icon>
                        <el-icon class="icon-button" v-if="question.questionNumber != questions.length" @click="() => swapQuestion(question.id, questions[question.questionNumber].id)">
                            <ArrowDown />
                        </el-icon>
                    </div>
                </div>
            </div>
            <el-divider />
        </div>
        <el-button v-if="props.mode == 'edit'" class="button-bottom" @click="addQuestion">
            <el-icon><Plus /></el-icon>
        </el-button>
        <el-button v-if="props.mode == 'fill'" class="button-bottom" @click="submitApplication" >
            提交申请
        </el-button>
        <div v-if="props.mode == 'show' && application?.canApprove" class="approve-block">
            <el-button  size="large" class="approve-btn" @click="() => approve(false)">拒绝</el-button>
            <el-button  size="large" class="approve-btn" @click="() => approve(true)">同意</el-button>
        </div>
    </div>
</template>

<style scoped>
.question-row, .question-main, .questions {
    width: 100%;
}

.question-main {
    display: flex;
    justify-content: start;
}
.question-number {
    padding-right: 30px;
    width: 20px;
    font-size: x-large; 
    color: #606266;
}
.question-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    margin-right: 20px;
}
.question-type {
    width: 90px;
}
.question-control {
    margin-left: 10px;
    width: 80px;

    display: flex;
    flex-direction: column;
    justify-content: space-between;
}
.question-move {
    display: flex;
    flex-direction: column;

}

.button-bottom {
    width: calc(100% - 60px);
    height: 50px;
    font-size: 18px;
    margin-bottom: 20px;
}

.approve-block {
    display: flex;
    align-items: center;
    justify-content: center;
}
.approve-btn {
    margin: 20px 50px 50px 50px;
}
</style>